#
#    Copyright (C) 2016 Francisco Javier Parra <franparpe@openmailbox.org>
#    Copyright (C) 2016 Enrique Ernesto Zayas <enrique.zayas@upc.edu>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#


import sys
import matplotlib
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from qtcam.gui_elements.mechanism_type import CamFollowerType
from qtcam.gui_elements.follower_type import FollowerType
from qtcam.gui_elements.cam_data import CamData
from qtcam.gui_elements.geometric_parameters import GeometricParameters
from qtcam.gui_elements.section_param_box import ParamBoxForSections
from qtcam.gui_elements.cam_profile_graph import CamProfileGraph
from qtcam.gui_elements.curvature_pressure_graph import CurvaturePressureGraph
from qtcam.gui_elements.position_dialog import PositionGraphDialog
from qtcam.gui_elements.velocity_dialog import VelocityGraphDialog
from qtcam.gui_elements.acceleration_dialog import AccelerationGraphDialog
from qtcam.gui_elements.jerk_dialog import JerkGraphDialog
from qtcam.gui_elements.summary import Summary
from qtcam.tools.get_directories import get_user_directory
from qtcam.core.export_engine import export_profile_to_dxf
from qtcam.core.export_engine import export_profile_and_conj_to_dxf
from qtcam.gui_elements.recopilation import Recopilation
from qtcam.gui_elements.about_qtcam import AboutQtCAM

from qtcam.core.cams import Cam

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QTabWidget
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QWidget, QSizePolicy
from PyQt5.QtWidgets import QScrollArea
from PyQt5.QtWidgets import QFormLayout
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QMenuBar
from PyQt5.QtWidgets import QMenu
from PyQt5.QtWidgets import QAction
from PyQt5.QtWidgets import QMessageBox



try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QApplication.translate(context, text, disambig)


class Ui_MainWindow(QMainWindow):
    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        self.number_of_sections = 0
        self.current_section = 0
        self.theCam = Cam()
        self.bezierAdvancedMode = False
        self.isConstWidth = False
        self.isTranslatingMov = True
        self.setupUi(self)

    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(1100, 720)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.horizontalLayout_2 = QHBoxLayout(self.centralwidget)
        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
        self.tab_main = QTabWidget(self.centralwidget)
        self.tab_main.setEnabled(True)
        self.tab_main.setAutoFillBackground(True)
        self.designTabC = QtWidgets.QWidget()
        self.tab_main.addTab(self.designTabC, "Tab1")
        self.designLayout = QHBoxLayout(self.designTabC)
        
        # self.gridLayout = QtGui.QGridLayout(self.designTabC)


        # the subtab
        self.startingDataTab = QWidget(self.designTabC)
        self.subTab = QTabWidget(self.designTabC)
        self.subTab.addTab(self.startingDataTab, "Starting data")
        # subtab 2
        self.movLawsSTabC = QWidget(self.designTabC)
        self.subTab.addTab(self.movLawsSTabC, "Movement law design")
        self.movLawsSTabC_Vert = QVBoxLayout(self.movLawsSTabC)

        
        self.startingData_Hbox = QHBoxLayout(self.startingDataTab)

        # left container:
        self.leftContainer = QWidget(self.startingDataTab)
        self.startingData_Hbox.addWidget(self.leftContainer)
        self.leftContainer_VLayout = QVBoxLayout(self.leftContainer)
        self.designLayout.addWidget(self.subTab)
         
        # Graph container
        self.future_graph = QWidget(self.designTabC)
        self.designLayout.addWidget(self.future_graph)
        # Vertical layout
        self.vertLayout_graph = QVBoxLayout(self.future_graph)

        # initialize new window
        self.CreateGraphPositionWindow()
        self.CreateGraphVelocityWindow()
        self.CreateGraphAccelerationWindow()
        self.CreateGraphJerkWindow()
        
        # Placing
        self.camFollowTypeBox = CamFollowerType(self.leftContainer)
        self.leftContainer_VLayout.addWidget(self.camFollowTypeBox)
        
        self.camDataBox = CamData(self.leftContainer)
        self.leftContainer_VLayout.addWidget(self.camDataBox)

        self.followTypeSelBox = FollowerType(self.leftContainer)
        self.leftContainer_VLayout.addWidget(self.followTypeSelBox)

        self.geomParametersBox = GeometricParameters(self.leftContainer)
        self.leftContainer_VLayout.addWidget(self.geomParametersBox)

        # box_Container
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        self.box_Container = QScrollArea(self.movLawsSTabC)
        self.box_Container.setSizePolicy(sizePolicy)
        self.box_Container.setAutoFillBackground(True)
        self.box_Container.setWidgetResizable(True)
        self.box_contents = QWidget(self.box_Container)
        self.box_contents.setGeometry(QtCore.QRect(0, 0, 585, 378))
        # self.box_Container_Vert = QtGui.QVBoxLayout(self.box_Container)
        # self.box_Container_Vert.addWidget(self.box_contents)
        self.box_contents_Form = QFormLayout(self.box_contents)
        self.movLawsSTabC_Vert.addWidget(self.box_Container)
        self.box_Container.setWidget(self.box_contents)

        # Making a container for the buttons
        butContainer_size = QSizePolicy(QSizePolicy.Fixed,
                                        QSizePolicy.Fixed)
        self.buttonContainer = QWidget(self.movLawsSTabC)
        self.butContainer_HLayout = QHBoxLayout(self.buttonContainer)
        self.buttonContainer.setSizePolicy(butContainer_size)
        self.movLawsSTabC_Vert.addWidget(self.buttonContainer)

        # Make a button to trigger the ploting
        self.plotButton = QPushButton(self.buttonContainer)
        self.plotButton.setText(_fromUtf8("Plot"))
        buttonSize = QSizePolicy(QSizePolicy.Fixed,
                                 QSizePolicy.Fixed)
        self.plotButton.setSizePolicy(buttonSize)
        self.butContainer_HLayout.addWidget(self.plotButton)

        # Making a button to trigger the self.profile generation
        self.profileButton = QPushButton(self.movLawsSTabC)
        self.profileButton.setText(_fromUtf8("Generate Profile"))
        self.profileButton.setSizePolicy(buttonSize)
        self.butContainer_HLayout.addWidget(self.profileButton)

        
        # Box with the parameters
        self.InitializeSectionParamBoxList()
        

        self.horizontalLayout_2.addWidget(self.tab_main)
        MainWindow.setCentralWidget(self.centralwidget)
        
        # The menubar
        self.menubar = QMenuBar(MainWindow)
        # self.menubar.setGeometry(QtCore.QRect(0, 0, 1000, 19))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.menuFile = QMenu(self.menubar)
        self.menuFile.setObjectName(_fromUtf8("menuFile"))
        # self.menuGraphic = QtGui.QMenu(self.menuFile)
        # self.menuGraphic.setObjectName(_fromUtf8("menuGraphic"))
        MainWindow.setMenuBar(self.menubar)
        # self.statusbar = QtGui.QStatusBar(MainWindow)
        # self.statusbar.setObjectName(_fromUtf8("statusbar"))
        # MainWindow.setStatusBar(self.statusbar)
        # self.actionSave = QtGui.QAction(MainWindow)
        # self.actionSave.setObjectName(_fromUtf8("actionSave"))
        self.actionExport = QAction(MainWindow)
        self.actionExport.setObjectName(_fromUtf8("actionExport"))
        # self.actionSave_2 = QtGui.QAction(MainWindow)
        # self.actionSave_2.setObjectName(_fromUtf8("actionSave_2"))
        # self.actionSave_as = QtGui.QAction(MainWindow)
        # self.actionSave_as.setObjectName(_fromUtf8("actionSave_as"))
        # self.actionOpen = QtGui.QAction(MainWindow)
        # self.actionOpen.setObjectName(_fromUtf8("actionOpen"))
        # self.actionSave_as_2 = QtGui.QAction(MainWindow)
        # self.actionSave_as_2.setObjectName(_fromUtf8("actionSave_as_2"))
        # self.actionNew = QtGui.QAction(MainWindow)
        # self.actionNew.setObjectName(_fromUtf8("actionNew"))
        # self.menuGraphic.addAction(self.actionSave_2)
        # self.menuGraphic.addAction(self.actionSave_as)
        # self.menuFile.addAction(self.actionNew)
        # self.menuFile.addAction(self.actionOpen)
        # self.menuFile.addSeparator()
        # self.menuFile.addAction(self.actionSave)
        # self.menuFile.addAction(self.actionSave_as_2)
        self.menuFile.addAction(self.actionExport)
        # self.menuFile.addSeparator()
        # self.menuFile.addAction(self.menuGraphic.menuAction())
        self.menubar.addAction(self.menuFile.menuAction())

        # Adding the export cam profile action
        self.actionExport.triggered.connect(self.export_cam_dxf)
        
        # Adding the "View" menu
        self.menuView = QMenu(self.menubar)
        self.menuView.setTitle("&View")
        self.menubar.addMenu(self.menuView)

        # Adding the "Help" menu
        self.menuHelp = QMenu(self.menubar)
        self.menuHelp.setTitle("&Help")
        self.menubar.addMenu(self.menuHelp)

        # Adding "about"
        self.actionAbout = QAction(MainWindow)
        self.actionAbout.setText(_fromUtf8("&About"))
        self.menuHelp.addAction(self.actionAbout)
        self.aboutWindow = AboutQtCAM(MainWindow)
        self.actionAbout.triggered.connect(self.aboutWindow.show)
        
        # The position plot for view
        self.actionViewPosition = QAction(MainWindow)
        self.actionViewPosition.setText(_fromUtf8("&Position"))
        self.menuView.addAction(self.actionViewPosition)
        self.actionViewPosition.triggered.connect(self.GraphPositionOnWindow)

        # The velocity plot for view
        self.actionViewVelocity = QAction(MainWindow)
        self.actionViewVelocity.setText(_fromUtf8("&Velocity"))
        self.menuView.addAction(self.actionViewVelocity)
        self.actionViewVelocity.triggered.connect(self.GraphVelocityOnWindow)

        # The acceleration plot view
        self.actionViewAcceleration = QAction(MainWindow)
        self.actionViewAcceleration.setText(_fromUtf8("&Acceleration"))
        self.menuView.addAction(self.actionViewAcceleration)
        self.actionViewAcceleration.triggered.connect(self.GraphAccelerationOnWindow)

        # The otherJerk plot view
        self.actionViewJerk = QAction(MainWindow)
        self.actionViewJerk.setText(_fromUtf8("&Jerk"))
        self.menuView.addAction(self.actionViewJerk)
        self.actionViewJerk.triggered.connect(self.GraphJerkOnWindow)

        # Graphs
        self.CreateGraphsPVAJ()

        # Connections
        self.camDataBox.connectNsections(self.ModNumberOfBoxes)
        self.plotButton.clicked.connect(self.Ploting)
        self.profileButton.clicked.connect(self.triggerCamGen)
        self.camFollowTypeBox.connect(self.changeGeomParambox)
        self.followTypeSelBox.connect(self.changeGeomParambox)
        self.followTypeSelBox.connect(self.changeBoxesLabels)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        # MainWindow.setTabOrder(self.SpinBox_numSec, self.boxFollower_movement)
        # MainWindow.setTabOrder(self.boxFollower_movement, self.pushButton)
        # MainWindow.setTabOrder(self.pushButton, self.box_Container)
        # MainWindow.setTabOrder(self.box_Container, self.initial_Angle)
        # MainWindow.setTabOrder(self.initial_Angle, self.end_Angle)
        # MainWindow.setTabOrder(self.end_Angle, self.typeList)
        # MainWindow.setTabOrder(self.typeList, self.initial_Displacement)
        # MainWindow.setTabOrder(self.initial_Displacement, self.final_Displacement)
        # MainWindow.setTabOrder(self.final_Displacement, self.positionButton)
        # MainWindow.setTabOrder(self.positionButton, self.velocityButton)
        # MainWindow.setTabOrder(self.velocityButton, self.lineEdit_l1)
        # MainWindow.setTabOrder(self.lineEdit_l1, self.jerkButton)
        # MainWindow.setTabOrder(self.jerkButton, self.accelerationButton)

        # Creating Dialogs
        self.CreateUseNumbersMessage()
        self.CreateLackOfParametersMessage()

        # Other Tabs
        self.CreateResultTab()

    def CreateResultTab(self):
        """ The other tab 
        """
        self.resultTab = QWidget(self)
        self.tab_main.addTab(self.resultTab, "Results")

        # layout
        self.resultTabHLay = QHBoxLayout(self.resultTab)

        # subtab environment
        self.subTabResults = QTabWidget(self.resultTab)
        self.resultTabHLay.addWidget(self.subTabResults)
        # Create the self.profile subtab
        self.profileTab = QWidget(self.resultTab)
        self.subTabResults.addTab(self.profileTab, "Cam profile")
        self.subTabProfileHbox = QHBoxLayout(self.profileTab)

        # Place the cam self.profile graph
        self.camProfileGraph = CamProfileGraph(self.profileTab)
        self.subTabProfileHbox.addWidget(self.camProfileGraph)

        # Place the curvature angle
        self.curvaturePressureGraph = CurvaturePressureGraph(self.profileTab)
        self.subTabProfileHbox.addWidget(self.curvaturePressureGraph)

        # the other subtab
        self.summaryTab = QWidget(self.resultTab)
        self.subTabResults.addTab(self.summaryTab, _fromUtf8("Summary"))
        self.subTabCurvaturePressureVbox = QVBoxLayout(self.summaryTab)

        #Create the summary table
        self.summary = Summary(self.summaryTab)
        self.subTabCurvaturePressureVbox.addWidget(self.summary)

        # Create the recopilation
        self.recopilation = Recopilation(self.summaryTab)
        self.subTabCurvaturePressureVbox.addWidget(self.recopilation)
        
    def CreateGraphPositionWindow(self):
        self.positionPlotWindow = PositionGraphDialog(self)

    def GraphPositionOnWindow(self):
        if self.isConstWidth:
            self.positionPlotWindow.Graph(self.theCam,
                                          self.otherAbci,
                                          self.otherDis)
        else:
            self.positionPlotWindow.Graph(self.theCam)
        
    def CreateGraphVelocityWindow(self):
        self.velocityPlotWindow = VelocityGraphDialog(self)

    def GraphVelocityOnWindow(self):
        if self.isConstWidth:
            self.velocityPlotWindow.Graph(self.theCam,
                                          self.otherAbci,
                                          self.otherVel)
        else:
            self.velocityPlotWindow.Graph(self.theCam)

    def CreateGraphAccelerationWindow(self):
        self.accelerationPlotWindow = AccelerationGraphDialog(self)

    def GraphAccelerationOnWindow(self):
        if self.isConstWidth:
            self.accelerationPlotWindow.Graph(self.theCam,
                                              self.otherAbci,
                                              self.otherAccel)
        else:
            self.accelerationPlotWindow.Graph(self.theCam)
        
    def CreateGraphJerkWindow(self):
        self.graphJerkWindow = JerkGraphDialog(self)

    def GraphJerkOnWindow(self):
        if self.isConstWidth:
            self.graphJerkWindow.Graph(self.theCam,
                                       self.otherAbci,
                                       self.otherJerk)
        else:
            self.graphJerkWindow.Graph(self.theCam)

    def CreateGraphsPVAJ(self):
        self.graphPVAJ = Figure()
        self.canvasPVAJ = FigureCanvas(self.graphPVAJ)
        self.vertLayout_graph.addWidget(self.canvasPVAJ)
        self.toolBarPVAJ = NavigationToolbar(self.canvasPVAJ, self.future_graph)
        self.vertLayout_graph.addWidget(self.toolBarPVAJ)

        self.positionPlot = self.graphPVAJ.add_subplot(411)
        self.velocityPlot = self.graphPVAJ.add_subplot(412)
        self.accelPlot = self.graphPVAJ.add_subplot(413)
        self.jerkPlot = self.graphPVAJ.add_subplot(414)
        
        # self.positionPlot.set_title(_fromUtf8("Position"))
        self.positionPlot.set_xlabel(_fromUtf8("Angle of rotation [º]"))
        self.positionPlot.set_ylabel(_fromUtf8("S [mm]"))

        # self.velocityPlot.set_title(_fromUtf8("Velocity"))
        self.velocityPlot.set_xlabel(_fromUtf8("Angle of rotation [º]"))
        self.velocityPlot.set_ylabel(_fromUtf8("V [mm/s]"))
        # self.accelPlot.set_title(_fromUtf8("Acceleration"))
        self.accelPlot.set_xlabel(_fromUtf8("Angle of rotation [º]"))
        self.accelPlot.set_ylabel(_fromUtf8("A [mm/s²]"))

        # self.jerkPlot.set_title(_fromUtf8("Jerk"))
        self.jerkPlot.set_xlabel(_fromUtf8("Angle of rotation [º]"))
        self.jerkPlot.set_ylabel(_fromUtf8("J [mm/s³]"))

        self.graphPVAJ.tight_layout()
        
    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "QtCAM", None))

        self.tab_main.setTabText(self.tab_main.indexOf(self.designTabC), _translate("MainWindow", "Cam design process", None))
        self.menuFile.setTitle(_translate("MainWindow", "&File", None))
        # self.menuGraphic.setTitle(_translate("MainWindow", "Graphic", None))
        # self.actionSave.setText(_translate("MainWindow", "Save", None))
        self.actionExport.setText(_translate("MainWindow", "Export", None))
        # self.actionSave_2.setText(_translate("MainWindow", "Save", None))
        # self.actionSave_as.setText(_translate("MainWindow", "Save as", None))
        # self.actionOpen.setText(_translate("MainWindow", "Open", None))
        # self.actionSave_as_2.setText(_translate("MainWindow", "Save as", None))
        # self.actionNew.setText(_translate("MainWindow", "New", None))

    def InitializeSectionParamBoxList(self):
        self.secParamBoxList = []
        
    def AddBox(self, currentPlace):
        self.secParamBoxList.append(ParamBoxForSections(self.box_contents,
                                                        currentPlace,
                                                        self.isTranslatingMov))
        # self.box_Container_Form.setWidget(currentPlace+1,
        #                                   QtGui.QFormLayout.SpanningRole,
        #                                   self.secParamBoxList[currentPlace])
        self.box_contents_Form.addWidget(self.secParamBoxList[currentPlace])
        
    def DeleteBox(self, currentPlace):
        """This method deletes the box with all the parameters"""
        self.secParamBoxList[currentPlace].DeleteItsElements()
        del(self.secParamBoxList[currentPlace])
        
    def ModNumberOfBoxes(self, value):
        self.number_of_sections = value
        # we count from zero and not from one
        while self.current_section < self.number_of_sections:
            self.AddBox(self.current_section)
            print("Created box", self.current_section)
            self.theCam.add_cam_section()
            self.current_section += 1

        while self.current_section > self.number_of_sections:
            self.DeleteBox(self.current_section - 1)
            print("Deleted box", self.current_section - 1)
            self.theCam.del_cam_section(-1)
            self.current_section -= 1

    def SwitchBezContPoly(self, check, currentIndex):
        print("checkB_ControlPoly is", check)
        self.theCam.sections[currentIndex].showBezierOrdinates = True


    def Ploting(self):
        """Plot the whole thing
        """
        for box in self.secParamBoxList:
            self.PassValuesToCam(box)

        self.PrintToPVAJ()
        ### From here
        mechanismType = self.camFollowTypeBox.getMechanismType()
        bilateralConstWidth = _fromUtf8("cam-follower bilateral with constant width")
        if mechanismType == bilateralConstWidth:
            self.summary.populateCommonTableCW(self.theCam)
        else:
            self.summary.populateCommonTable(self.theCam)
        
    def PassValuesToCam(self, box):
        """This method puts all parameters from the
        QLineEdit to the cam object
        """
        index = box.index
        secType = box.getLawType()
        print(secType)
        self.theCam.sections[index].StartAngle = box.getInitialAngle()
        self.theCam.sections[index].EndAngle = box.getEndAngle()
        self.theCam.sections[index].LowestPosition = box.getInitialPosition()
        self.theCam.sections[index].HighestPosition = box.getDisplacement()
        angularVelocity = self.camDataBox.getAngularVelocity()
        self.theCam.sections[index].AngularVelocity = angularVelocity
        self.theCam.change_section_type(index, secType)
        print(self.theCam.sections[index].StartAngle)
        print(self.theCam.sections[index].EndAngle)
        print(self.theCam.sections[index].LowestPosition)
        print(self.theCam.sections[index].HighestPosition)

        if secType == _fromUtf8("Bezier"):
            bezCont = box.getBezierContinuity()
            bezMode = box.getBezierMode()
            print(bezMode)
            if bezMode == _fromUtf8("Maximum selection"):
                print("here")
                self.theCam.sections[index].vector = "simple detention"
            else:
                self.theCam.sections[index].vector = "double detention"
            self.theCam.sections[index].continuity = bezCont
        else:
            pass


    def CreateUseNumbersMessage(self):
        """This method creates the dialog that informs
        the user not to use the letters instead of numbers
        """
        self.messageMustBeNumbers = QMessageBox(self)
        self.messageMustBeNumbers.setIcon(QMessageBox.Information)
        message = "Values must be numbers and not letters"
        self.messageMustBeNumbers.setText(message)

        
    def UseNumbersMessage(self):
        """Prints a warning to the user that tells him/her to use numbers
        instead of other character
        """
        self.messageMustBeNumbers.exec_()

    def CreateLackOfParametersMessage(self):
        """Creates the dialog to inform the user about that he forgot
        to put values on some boxes
        """
        self.messageLackValues = QMessageBox(self)
        self.messageLackValues.setIcon(QMessageBox.Information)
        self.messageLackValues.setText("Not all values has been introduced")

    def LackOfParametersMessage(self):
        """Shows the dialog that informs the user that not all has
        been introduced
        """
        self.messageLackValues.exec_()

    def PrintToPVAJ(self):
        """This method draws on the graphPVAJ
        """
        self.isConstWidth = False
        self.positionPlot.clear()
        self.velocityPlot.clear()
        self.accelPlot.clear()
        self.jerkPlot.clear()

        # follower Type
        flatRot = _fromUtf8("Flat-faced rotating follower")
        circRot = _fromUtf8("Circular-faced rotating follower")
        followerType = self.followTypeSelBox.getFollowerType()

        # The text in the labels
        labelAngleOfRot = _fromUtf8("Angle of rotation [º]")

        if (followerType == flatRot) or (followerType == circRot):
            self.positionPlot.set_ylabel(_fromUtf8("S [º]"))
            self.velocityPlot.set_ylabel(_fromUtf8("V [º/s]"))
            self.accelPlot.set_ylabel(_fromUtf8("A [º/s²]"))
            self.jerkPlot.set_ylabel(_fromUtf8("J [º/s³]"))

        else:
            self.positionPlot.set_ylabel(_fromUtf8("S [mm]"))
            self.velocityPlot.set_ylabel(_fromUtf8("V [mm/s]"))
            self.accelPlot.set_ylabel(_fromUtf8("A [mm/s²]"))
            self.jerkPlot.set_ylabel(_fromUtf8("J [mm/s³]"))

        # The labels must be recalled
        self.positionPlot.set_xlabel(labelAngleOfRot)
        self.velocityPlot.set_xlabel(labelAngleOfRot)
        self.accelPlot.set_xlabel(labelAngleOfRot)
        self.jerkPlot.set_xlabel(labelAngleOfRot)

        # The grid must be placed
        self.positionPlot.grid(True)
        self.velocityPlot.grid(True)
        self.accelPlot.grid(True)
        self.jerkPlot.grid(True)

        # Time to plot
        for section in self.theCam.sections:
            section.CreateYaxisPosition()
            section.CreateYaxisVelocity()
            section.CreateYaxisAcceleration()
            section.CreateYaxisOverAcceleration()
            self.positionPlot.plot(section.abcissaeValues,
                                   section.ordinatePosition, "-")
            self.velocityPlot.plot(section.abcissaeValues,
                                   section.ordinateVelocity, "-")
            self.accelPlot.plot(section.abcissaeValues,
                                section.ordinateAcceleration, "-")
            self.jerkPlot.plot(section.abcissaeValues,
                               section.ordinateOverAcceleration, "-")

        if self.camFollowTypeBox.getMechanismType() == _fromUtf8("cam-follower bilateral with constant width"):
            self.isConstWidth = True
            self.theCam.createSecondHalf()
            (self.otherAbci,
             self.otherDis,
             self.otherVel,
             self.otherAccel,
             self.otherJerk) = self.theCam.returnOtherHalfParam()
            self.positionPlot.plot(self.otherAbci, self.otherDis, "-")
            self.velocityPlot.plot(self.otherAbci, self.otherVel, "-")
            self.accelPlot.plot(self.otherAbci, self.otherAccel, "-")
            self.jerkPlot.plot(self.otherAbci, self.otherJerk, "-")
            
        self.canvasPVAJ.draw()

    def changeBoxesLabels(self):
        """Makes the boxes change its lables
        """
        flatTrans = _fromUtf8("Flat-faced translating follower")
        circTrans = _fromUtf8("Circular-faced translating follower")
        flatRot = _fromUtf8("Flat-faced rotating follower")
        circRot = _fromUtf8("Circular-faced rotating follower")
        followerType = self.followTypeSelBox.getFollowerType()
        if (followerType == flatRot) or (followerType == circRot):
            self.isTranslatingMov = False
        else:
            self.isTranslatingMov = True

        i = 0
        while i < len(self.secParamBoxList):
            self.secParamBoxList[i].setTranslationMovement(self.isTranslatingMov)
            self.secParamBoxList[i].setLastLablesContent()
            i += 1

    def triggerCamGen(self):
        """This method triggers the self.profile generation
        and the result display
        """
        # mechanism_type
        unilateral = _fromUtf8("cam-follower unilateral contact")
        bilateral = _fromUtf8("cam-follower bilateral contact")
        bilateralConstWidth = _fromUtf8("cam-follower bilateral with constant width")
        mechanismType = self.camFollowTypeBox.getMechanismType()

        # follower Type
        flatTrans = _fromUtf8("Flat-faced translating follower")
        circTrans = _fromUtf8("Circular-faced translating follower")
        flatRot = _fromUtf8("Flat-faced rotating follower")
        circRot = _fromUtf8("Circular-faced rotating follower")
        followerType = self.followTypeSelBox.getFollowerType()
        if mechanismType == unilateral:
            if followerType == flatTrans:
                self.theCam.rb = self.geomParametersBox.getBaseRadius()
                self.theCam.beta = self.geomParametersBox.getInclination()
                self.theCam.excentricity = self.geomParametersBox.getExcentricity()
                self.profile = self.theCam.generateCamOutline(1)
                baseRadius = self.theCam.rb
                self.camProfileGraph.genProfileUnilateral(self.profile,
                                                          rb=baseRadius)
                x = self.theCam.abcissaeValues
                yCurvRad = self.theCam.curvatureRadiusList
                yPressAng = self.theCam.pressureAngleList
                self.curvaturePressureGraph.genCurvatureRadiusPlot(x, yCurvRad)
                self.curvaturePressureGraph.genPressureAnglePlot(x, yPressAng)
                # recopilation
                self.recopilation.unilateral_flat(self.theCam)
            elif followerType == circTrans:
                self.theCam.rb = self.geomParametersBox.getBaseRadius()
                self.theCam.followerRadius = self.geomParametersBox.getRollerRadius()
                self.theCam.excentricity = self.geomParametersBox.getExcentricity()
                self.profile = self.theCam.generateCamOutline(2)
                baseRadius = self.theCam.rb
                camOffset = self.theCam.offset
                self.camProfileGraph.genProfileUnilateral(self.profile,
                                                          offset=camOffset,
                                                          rb=baseRadius)
                x = self.theCam.abcissaeValues
                yCurvRad = self.theCam.curvatureRadiusList
                yPressAng = self.theCam.pressureAngleList
                self.curvaturePressureGraph.genCurvatureRadiusPlot(x, yCurvRad)
                self.curvaturePressureGraph.genPressureAnglePlot(x, yPressAng)
                # Recopilation
                self.recopilation.unilateral_circular(self.theCam)
            elif followerType == flatRot:
                self.theCam.rb = self.geomParametersBox.getBaseRadius()
                self.theCam.l1 = self.geomParametersBox.getDistanceBetRotationCenters()
                self.theCam.l2 = self.geomParametersBox.getArmFollowerLong()
                self.profile = self.theCam.generateCamOutline(4)
                baseRadius = self.theCam.rb
                self.camProfileGraph.genProfileUnilateral(self.profile,
                                                          rb=baseRadius)
                x = self.theCam.abcissaeValues
                yCurvRad = self.theCam.curvatureRadiusList
                yPressAng = self.theCam.pressureAngleList
                self.curvaturePressureGraph.genCurvatureRadiusPlot(x, yCurvRad)
                self.curvaturePressureGraph.genPressureAnglePlot(x, yPressAng)
                # Recopilation
                self.recopilation.unilateral_flat_angular(self.theCam)
            elif followerType == circRot:
                self.theCam.rb = self.geomParametersBox.getBaseRadius()
                self.theCam.followerRadius = self.geomParametersBox.getRollerRadius()
                self.theCam.l1 = self.geomParametersBox.getDistanceBetRotationCenters()
                self.theCam.l2 = self.geomParametersBox.getArmFollowerLong()
                self.profile = self.theCam.generateCamOutline(5)
                baseRadius = self.theCam.rb
                camOffset = self.theCam.offset
                self.camProfileGraph.genProfileUnilateral(self.profile,
                                                          offset=camOffset,
                                                          rb=baseRadius)
                x = self.theCam.abcissaeValues
                yCurvRad = self.theCam.curvatureRadiusList
                yPressAng = self.theCam.pressureAngleList
                self.curvaturePressureGraph.genCurvatureRadiusPlot(x, yCurvRad)
                self.curvaturePressureGraph.genPressureAnglePlot(x, yPressAng)
                # Recopilation
                self.recopilation.unilateral_circular_angular(self.theCam)
            else:
                print("error")
            # send data to the summary
            self.summary.populateMaxMinTable(self.theCam)

        elif mechanismType == bilateral:
            if followerType == flatTrans:
                self.theCam.rb = self.geomParametersBox.getBaseRadius()
                self.theCam.excentricity = self.geomParametersBox.getExcentricity()
                self.theCam.beta = self.geomParametersBox.getInclination()
                self.theCam.separation = self.geomParametersBox.getArmSeparation()
                self.profile1, self.profile2 = self.theCam.generateCamOutlineConjugate(0)
                rb1 = self.theCam.rb
                rb2 = self.theCam.rb2
                x = self.theCam.abcissaeValues
                yCurvRadUp = self.theCam.radiusOfCurvatureListUp
                yCurvRadLo = self.theCam.radiusOfCurvatureListLo
                yPressAngUp = self.theCam.pressureAngleListUp
                yPressAngLo = self.theCam.pressureAngleListLo
                self.camProfileGraph.genProfileBilateral(self.profile1,
                                                         self.profile2,
                                                         rb=rb1,
                                                         rb2=rb2)
                self.curvaturePressureGraph.genPressureAnglePlotBi(x,
                                                                   yPressAngUp,
                                                                   yPressAngLo)
                self.curvaturePressureGraph.genCurvatureRadiusPlotBi(x,
                                                                     yCurvRadUp,
                                                                     yCurvRadLo)
                # Recopilation
                self.recopilation.bilateral_flat_follower(self.theCam)
            elif followerType == circTrans:
                self.theCam.rb = self.geomParametersBox.getBaseRadius()
                self.theCam.excentricity = self.geomParametersBox.getExcentricity()
                self.theCam.followerRadius = self.geomParametersBox.getRollerRadius()
                self.theCam.separation = self.geomParametersBox.getArmSeparation()
                self.profile1, self.profile2 = self.theCam.generateCamOutlineConjugate(1)
                x = self.theCam.abcissaeValues
                yCurvRadUp = self.theCam.radiusOfCurvatureListUp
                yCurvRadLo = self.theCam.radiusOfCurvatureListLo
                yPressAngUp = self.theCam.pressureAngleListUp
                yPressAngLo = self.theCam.pressureAngleListLo
                
                camOffset1 = self.theCam.camOffset1
                camOffset2 = self.theCam.camOffset2
                rb1 = self.theCam.rb
                rb2 = self.theCam.rb2
                self.camProfileGraph.genProfileBilateral(self.profile1,
                                                         self.profile2,
                                                         offset1=camOffset1,
                                                         offset2=camOffset2,
                                                         rb=rb1,
                                                         rb2=rb2)
                self.curvaturePressureGraph.genPressureAnglePlotBi(x,
                                                                   yPressAngUp,
                                                                   yPressAngLo)
                self.curvaturePressureGraph.genCurvatureRadiusPlotBi(x,
                                                                     yCurvRadUp,
                                                                     yCurvRadLo)
                # Recopilation
                self.recopilation.bilateral_circular(self.theCam)
            elif followerType == flatRot:
                self.theCam.rb = self.geomParametersBox.getBaseRadius()
                self.theCam.l1 = self.geomParametersBox.getDistanceBetRotationCenters()
                self.theCam.beta = self.geomParametersBox.getArmsAperture()
                self.profile1, self.profile2 = self.theCam.generateCamOutlineConjugate(2)
                x = self.theCam.abcissaeValues
                yCurvRadUp = self.theCam.radiusOfCurvatureListUp
                yCurvRadLo = self.theCam.radiusOfCurvatureListLo
                yPressAngUp = self.theCam.pressureAngleListUp
                yPressAngLo = self.theCam.pressureAngleListLo

                rb1 = self.theCam.rb
                rb2 = self.theCam.rb2
                self.camProfileGraph.genProfileBilateral(self.profile1,
                                                         self.profile2,
                                                         rb=rb1,
                                                         rb2=rb2)
                self.curvaturePressureGraph.genPressureAnglePlotBi(x,
                                                                   yPressAngUp,
                                                                   yPressAngLo)
                self.curvaturePressureGraph.genCurvatureRadiusPlotBi(x,
                                                                     yCurvRadUp,
                                                                     yCurvRadLo)
                # Recopilation
                self.recopilation.bilateral_flat_angular(self.theCam)
            elif followerType == circRot:
                self.theCam.rb = self.geomParametersBox.getBaseRadius()
                self.theCam.followerRadius = self.geomParametersBox.getRollerRadius()
                self.theCam.l1 = self.geomParametersBox.getDistanceBetRotationCenters()
                self.theCam.l3sup = self.geomParametersBox.getUpperArmLength()
                self.theCam.l3inf = self.geomParametersBox.getLowerArmLength()
                self.theCam.beta = self.geomParametersBox.getArmsAperture()
                self.profile1, self.profile2 = self.theCam.generateCamOutlineConjugate(3)
                x = self.theCam.abcissaeValues
                yCurvRadUp = self.theCam.radiusOfCurvatureListUp
                yCurvRadLo = self.theCam.radiusOfCurvatureListLo
                yPressAngUp = self.theCam.pressureAngleListUp
                yPressAngLo = self.theCam.pressureAngleListLo
                camOffset1 = self.theCam.camOffset1
                camOffset2 = self.theCam.camOffset2
                rb1 = self.theCam.rb
                rb2 = self.theCam.rb2
                self.camProfileGraph.genProfileBilateral(self.profile1,
                                                         self.profile2,
                                                         offset1=camOffset1,
                                                         offset2=camOffset2,
                                                         rb=rb1,
                                                         rb2=rb2)
                self.curvaturePressureGraph.genPressureAnglePlotBi(x,
                                                                   yPressAngUp,
                                                                   yPressAngLo)
                self.curvaturePressureGraph.genCurvatureRadiusPlotBi(x,
                                                                     yCurvRadUp,
                                                                     yCurvRadLo)
                # Recopilation
                self.recopilation.bilateral_circular_angular(self.theCam)
            else:
                print("error")
            self.summary.populateMaxMinTableConjugate(self.theCam)
            

        else:
            self.theCam.rb = self.geomParametersBox.getBaseRadius()
            self.theCam.excentricity = self.geomParametersBox.getExcentricity()
            self.theCam.beta = self.geomParametersBox.getInclination()
            self.profile = self.theCam.GenerateDesmoPlain()

            rb1 = self.theCam.rb
            self.camProfileGraph.genProfileUnilateral(self.profile,
                                                      rb=rb1)
            x = self.theCam.abcissaeValues
            yCurvRad = self.theCam.curvatureRadiusList
            yPressAng = self.theCam.pressureAngleList
            self.curvaturePressureGraph.genCurvatureRadiusPlot(x, yCurvRad)
            self.curvaturePressureGraph.genPressureAnglePlot(x, yPressAng)
            # Now the summary
            self.summary.populateMaxMinTable(self.theCam)

    def changeGeomParambox(self):
        # mechanism_type
        unilateral = _fromUtf8("cam-follower unilateral contact")
        bilateral = _fromUtf8("cam-follower bilateral contact")
        mechanismType = self.camFollowTypeBox.getMechanismType()

        # Changing the follower type box depending on the input
        self.followTypeSelBox.setContents(mechanismType)

        # follower Type
        flatTrans = _fromUtf8("Flat-faced translating follower")
        circTrans = _fromUtf8("Circular-faced translating follower")
        flatRot = _fromUtf8("Flat-faced rotating follower")
        circRot = _fromUtf8("Circular-faced rotating follower")
        followerType = self.followTypeSelBox.getFollowerType()
        if mechanismType == unilateral:
            if followerType == flatTrans:
                self.geomParametersBox.DestroyPrevious()
                self.geomParametersBox.CreateFlatTranslationUnilateral()
            elif followerType == circTrans:
                self.geomParametersBox.DestroyPrevious()
                self.geomParametersBox.CreateCircularTranslationUnilateral()
            elif followerType == flatRot:
                self.geomParametersBox.DestroyPrevious()
                self.geomParametersBox.CreateFlatAngularUnilateral()
            elif followerType == circRot:
                self.geomParametersBox.DestroyPrevious()
                self.geomParametersBox.CreateCircularAngularUnilateral()
            else:
                print("error")

        elif mechanismType == bilateral:
            if followerType == flatTrans:
                self.geomParametersBox.DestroyPrevious()
                self.geomParametersBox.CreateFlatTranslationDesmodromic()
            elif followerType == circTrans:
                self.geomParametersBox.DestroyPrevious()
                self.geomParametersBox.CreateCircularTranslationDesmodromic()
            elif followerType == flatRot:
                self.geomParametersBox.DestroyPrevious()
                self.geomParametersBox.CreateFlatAngularDesmodromic()
            elif followerType == circRot:
                self.geomParametersBox.DestroyPrevious()
                self.geomParametersBox.CreateCircularAngularDesmodromic()
            else:
                print("error")

        else:
            pass

            # from

    def export_cam_dxf(self):
        """Export the cam to a DXF format
        """
        print("Works")
        mechanismType = self.camFollowTypeBox.getMechanismType()
        bilateral = _fromUtf8("cam-follower bilateral contact")
        caption = _fromUtf8("Export cam profile")
        home = get_user_directory()
        filters = _fromUtf8("Drawing Exchange Format (*.dxf)")
        PATH = QFileDialog.getSaveFileName(self,  # parent is mainWindow
                                           caption,  # the caption
                                           home,  # default dir
                                           filters)
        print(PATH)
        if PATH:
            if mechanismType == bilateral:
                export_profile_and_conj_to_dxf(self.profile1,
                                               self.profile2,
                                               PATH[0])
            else:
                export_profile_to_dxf(self.profile, PATH[0])
        else:
            pass


def main():
    qtCam = QApplication(sys.argv)
    window = Ui_MainWindow()
    window.show()
    sys.exit(qtCam.exec_())
    
if __name__ == '__main__':
    main()
